package edu.ptu.acl.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import edu.ptu.acl.common.MyConstants;
import edu.ptu.acl.common.RequestHolder;
import edu.ptu.acl.common.ResultVO;
import edu.ptu.acl.dto.TokenPayload;
import edu.ptu.acl.entity.*;
import edu.ptu.acl.service.*;
import edu.ptu.acl.utils.JWTUtil;
import edu.ptu.acl.utils.MD5Util;
import edu.ptu.acl.utils.RedisUtil;
import edu.ptu.acl.utils.SnowIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Length;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Size;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@RestController
@Slf4j
@Validated
public class LoginController {

    @Resource
    private IUserService userService;
    @Resource
    private IAclService aclService;

    @GetMapping("/login/{userName}/{password}")
    public ResultVO login(@PathVariable("userName")@Length(min = 1,max = 20,message = "用户名长度必须是1-20个字符") String userName
            , @PathVariable("password")@Size(min = 6, max = 16, message = "密码长度必须是6-16个字符") String password){
        log.info("tel或email为{}的用户尝试登陆",userName);

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("telephone",userName).or().eq("email",userName);
        User user = userService.getOne(queryWrapper);
        if (user == null){
            // 用户不存在
            return ResultVO.fail(MyConstants.ResultCode.USER_NOT_EXIST);
        }else if(!StringUtils.equals(user.getPassword(), MD5Util.encrypt(password))){
            // 密码错误
            return ResultVO.fail(MyConstants.ResultCode.USER_PASS_ERROR);
        }else if (StringUtils.equals(user.getStatus(),MyConstants.UserState.FREEZE.getState())){
            // 用户被冻结
            return ResultVO.fail(MyConstants.ResultCode.USER_IS_FREEZE);
        }else{
            log.info("id为{}的用户登陆成功",user.getId());
            // login success
            Long snowId = SnowIdWorker.getSnowId();

            // redis插入值，设置过期时间30分钟
            RedisUtil.setValue(user.getId().toString(), snowId.toString()
                    , MyConstants.RedisExTime.USER_LOGIN_EX_TIME.getExTime(), MyConstants.RedisExTime.USER_LOGIN_EX_TIME.getTimeUnit());
            RedisUtil.setValue(snowId.toString(),user
                    , MyConstants.RedisExTime.USER_LOGIN_EX_TIME.getExTime(), MyConstants.RedisExTime.USER_LOGIN_EX_TIME.getTimeUnit());
            //jwt
            String token = JWTUtil.getToken(user.getId(),snowId);
            return ResultVO.success(token);
        }
    }

    @GetMapping("/getInfo")
    public ResultVO getInfo(){
        List<String> componentList = new ArrayList<>();
        List<String> buttonList = new ArrayList<>();

        List<Acl> currentUserAclList = aclService.getCurrentUserAclList();

        if (CollectionUtils.isNotEmpty(currentUserAclList)) {
            // 类型：0:接口1:按钮2:路由
            componentList = currentUserAclList.stream().filter(acl -> StringUtils.equals(acl.getType(),"2")).map(Acl::getComponent).collect(Collectors.toList());
            buttonList = currentUserAclList.stream().filter(acl -> StringUtils.equals(acl.getType(),"1")).map(Acl::getButtonId).collect(Collectors.toList());
        }
        User currentUser = RequestHolder.getCurrentUser();
        HashMap result = new HashMap();
        result.put("user",currentUser);
        result.put("componentList",componentList);
        result.put("buttonList",buttonList);
        return ResultVO.success(result);
    }


    @GetMapping("/logout")
    public ResultVO logout(HttpServletRequest servletRequest){

        String token = servletRequest.getHeader("Authorization");
        TokenPayload tokenPayload = JWTUtil.parseToken(token);
        Long userId = tokenPayload.getUserId();
        Long snowId = tokenPayload.getSnowId();
        RedisUtil.setValue(userId.toString(),"",0);
        RedisUtil.setValue(snowId.toString(),"",0);
        log.info("id为 {} 的用户退出登陆，清除redis成功",userId);
        return ResultVO.success();
    }

}
